package com.ruoyi.system.service.impl;

import java.util.*;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.IMbtiTestService;

/**
 * MBTI测试Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-01-21
 */
@Service
public class MbtiTestServiceImpl implements IMbtiTestService 
{
    private static final Logger logger = LoggerFactory.getLogger(MbtiTestServiceImpl.class);
    
    @Autowired
    private MbtiTestTypeMapper testTypeMapper;
    
    @Autowired
    private MbtiQuestionMapper questionMapper;
    
    @Autowired
    private MbtiOptionMapper optionMapper;
    
    @Autowired
    private MbtiTestRecordMapper testRecordMapper;
    
    @Autowired
    private MbtiAnswerMapper answerMapper;
    
    @Autowired
    private MbtiResultMapper resultMapper;
    
    @Autowired
    private MbtiPersonalityTypeMapper personalityTypeMapper;

    /**
     * 获取所有可用的测试类型
     */
    @Override
    public List<MbtiTestType> getAvailableTestTypes()
    {
        return testTypeMapper.selectAvailableTestTypes();
    }

    /**
     * 根据测试类型ID获取测试详情
     */
    @Override
    public MbtiTestType getTestTypeById(Long testTypeId)
    {
        return testTypeMapper.selectMbtiTestTypeByTestTypeId(testTypeId);
    }

    /**
     * 开始测试
     */
    @Override
    @Transactional
    public Long startTest(Long testTypeId, Long userId, String userName, String userEmail, String ipAddress, String userAgent)
    {
        // 验证测试类型是否存在且可用
        MbtiTestType testType = testTypeMapper.selectMbtiTestTypeByTestTypeId(testTypeId);
        if (testType == null || !"0".equals(testType.getStatus()))
        {
            throw new ServiceException("测试类型不存在或已停用");
        }

        // 创建测试记录
        MbtiTestRecord record = new MbtiTestRecord();
        record.setTestTypeId(testTypeId);
        record.setUserId(userId);
        record.setUserName(userName);
        record.setUserEmail(userEmail);
        record.setStartTime(DateUtils.getNowDate());
        record.setStatus("0"); // 进行中
        record.setIpAddress(ipAddress);
        record.setUserAgent(userAgent);
        record.setCreateTime(DateUtils.getNowDate());

        testRecordMapper.insertMbtiTestRecord(record);
        return record.getRecordId();
    }

    /**
     * 获取测试题目列表
     */
    @Override
    public List<Map<String, Object>> getTestQuestions(Long testTypeId)
    {
        List<MbtiQuestion> questions = questionMapper.selectQuestionsByTestTypeId(testTypeId);
        List<Map<String, Object>> result = new ArrayList<>();

        for (MbtiQuestion question : questions)
        {
            Map<String, Object> questionMap = new HashMap<>();
            questionMap.put("questionId", question.getQuestionId());
            questionMap.put("questionText", question.getQuestionText());
            questionMap.put("questionOrder", question.getQuestionOrder());
            questionMap.put("dimension", question.getDimension());

            // 获取选项
            List<MbtiOption> options = optionMapper.selectOptionsByQuestionId(question.getQuestionId());
            List<Map<String, Object>> optionList = new ArrayList<>();
            for (MbtiOption option : options)
            {
                Map<String, Object> optionMap = new HashMap<>();
                optionMap.put("optionId", option.getOptionId());
                optionMap.put("optionText", option.getOptionText());
                optionMap.put("optionValue", option.getOptionValue());
                optionMap.put("optionOrder", option.getOptionOrder());
                optionList.add(optionMap);
            }
            questionMap.put("options", optionList);
            result.add(questionMap);
        }

        // 按题目顺序排序
        result.sort((a, b) -> Integer.compare((Integer) a.get("questionOrder"), (Integer) b.get("questionOrder")));
        return result;
    }

    /**
     * 获取测试题目基本信息列表（仅包含ID和基本信息）
     */
    @Override
    public List<Map<String, Object>> getTestQuestionBasics(Long testTypeId)
    {
        List<MbtiQuestion> questions = questionMapper.selectQuestionsByTestTypeId(testTypeId);
        List<Map<String, Object>> result = new ArrayList<>();

        for (MbtiQuestion question : questions)
        {
            Map<String, Object> questionBasic = new HashMap<>();
            questionBasic.put("questionId", question.getQuestionId());
            questionBasic.put("questionOrder", question.getQuestionOrder());
            questionBasic.put("dimension", question.getDimension());
            // 不包含questionText和options，减少数据传输
            result.add(questionBasic);
        }

        // 按题目顺序排序
        result.sort((a, b) -> Integer.compare((Integer) a.get("questionOrder"), (Integer) b.get("questionOrder")));
        return result;
    }

    /**
     * 批量获取题目详情
     */
    @Override
    public List<Map<String, Object>> getQuestionsDetail(List<Long> questionIds)
    {
        List<Map<String, Object>> result = new ArrayList<>();
        
        for (Long questionId : questionIds)
        {
            try {
                Map<String, Object> questionDetail = getQuestionDetail(questionId);
                result.add(questionDetail);
            } catch (Exception e) {
                // 跳过获取失败的题目，不影响其他题目
                logger.warn("获取题目详情失败: questionId={}", questionId, e);
            }
        }
        
        return result;
    }

    /**
     * 预加载题目（智能预加载相邻题目）
     */
    @Override
    public List<Map<String, Object>> preloadQuestions(Long testTypeId, Integer currentIndex, Integer range)
    {
        // 获取题目ID列表
        List<MbtiQuestion> allQuestions = questionMapper.selectQuestionsByTestTypeId(testTypeId);
        allQuestions.sort((a, b) -> Integer.compare(a.getQuestionOrder(), b.getQuestionOrder()));
        
        List<Long> preloadIds = new ArrayList<>();
        
        // 计算预加载范围
        int start = Math.max(0, currentIndex - range);
        int end = Math.min(allQuestions.size(), currentIndex + range + 1);
        
        for (int i = start; i < end; i++) {
            if (i != currentIndex) { // 排除当前题目
                preloadIds.add(allQuestions.get(i).getQuestionId());
            }
        }
        
        return getQuestionsDetail(preloadIds);
    }

    /**
     * 获取单个题目详情
     */
    @Override
    public Map<String, Object> getQuestionDetail(Long questionId)
    {
        MbtiQuestion question = questionMapper.selectMbtiQuestionByQuestionId(questionId);
        if (question == null)
        {
            throw new ServiceException("题目不存在");
        }

        Map<String, Object> result = new HashMap<>();
        result.put("questionId", question.getQuestionId());
        result.put("questionText", question.getQuestionText());
        result.put("questionOrder", question.getQuestionOrder());
        result.put("dimension", question.getDimension());

        List<MbtiOption> options = optionMapper.selectOptionsByQuestionId(questionId);
        List<Map<String, Object>> optionList = new ArrayList<>();
        for (MbtiOption option : options)
        {
            Map<String, Object> optionMap = new HashMap<>();
            optionMap.put("optionId", option.getOptionId());
            optionMap.put("optionText", option.getOptionText());
            optionMap.put("optionValue", option.getOptionValue());
            optionMap.put("optionOrder", option.getOptionOrder());
            optionList.add(optionMap);
        }
        result.put("options", optionList);
        return result;
    }

    /**
     * 提交单个题目答案
     */
    @Override
    @Transactional
    public boolean submitAnswer(Long recordId, Long questionId, Long optionId)
    {
        // 验证测试记录
        if (!validateTestRecord(recordId))
        {
            return false;
        }

        // 获取选项信息
        MbtiOption option = optionMapper.selectMbtiOptionByOptionId(optionId);
        if (option == null || !option.getQuestionId().equals(questionId))
        {
            throw new ServiceException("选项不存在或不匹配");
        }

        // 检查是否已经回答过这个问题
        MbtiAnswer existingAnswer = answerMapper.selectAnswerByRecordIdAndQuestionId(recordId, questionId);
        if (existingAnswer != null)
        {
            // 更新答案
            existingAnswer.setOptionId(optionId);
            existingAnswer.setAnswerValue(option.getOptionValue());
            existingAnswer.setScore(option.getScore());
            existingAnswer.setAnswerTime(DateUtils.getNowDate());
            return answerMapper.updateMbtiAnswer(existingAnswer) > 0;
        }
        else
        {
            // 新增答案
            MbtiAnswer answer = new MbtiAnswer();
            answer.setRecordId(recordId);
            answer.setQuestionId(questionId);
            answer.setOptionId(optionId);
            answer.setAnswerValue(option.getOptionValue());
            answer.setScore(option.getScore());
            answer.setAnswerTime(DateUtils.getNowDate());
            return answerMapper.insertMbtiAnswer(answer) > 0;
        }
    }

    /**
     * 批量提交答案
     */
    @Override
    @Transactional
    public boolean submitAnswers(Long recordId, Map<Long, Long> answers)
    {
        for (Map.Entry<Long, Long> entry : answers.entrySet())
        {
            if (!submitAnswer(recordId, entry.getKey(), entry.getValue()))
            {
                return false;
            }
        }
        return true;
    }

    /**
     * 完成测试并计算结果
     */
    @Override
    @Transactional
    public MbtiResult completeTest(Long recordId)
    {
        // 验证测试记录
        MbtiTestRecord record = testRecordMapper.selectMbtiTestRecordByRecordId(recordId);
        if (record == null || !"0".equals(record.getStatus()))
        {
            throw new ServiceException("测试记录不存在或已完成");
        }

        // 获取所有答案
        List<MbtiAnswer> answers = answerMapper.selectAnswersByRecordId(recordId);
        if (answers.isEmpty())
        {
            throw new ServiceException("未找到答题记录");
        }

        // 计算各维度得分
        Map<String, Integer> scores = calculateDimensionScores(answers);

        // 确定人格类型
        String personalityType = determinePersonalityType(scores);

        // 更新测试记录状态
        record.setEndTime(DateUtils.getNowDate());
        record.setStatus("1"); // 已完成
        if (record.getStartTime() != null)
        {
            long duration = (record.getEndTime().getTime() - record.getStartTime().getTime()) / 1000;
            record.setDuration((int) duration);
        }
        testRecordMapper.updateMbtiTestRecord(record);

        // 保存测试结果
        MbtiResult result = new MbtiResult();
        result.setRecordId(recordId);
        result.setPersonalityType(personalityType);
        result.setEScore(scores.getOrDefault("E", 0));
        result.setIScore(scores.getOrDefault("I", 0));
        result.setSScore(scores.getOrDefault("S", 0));
        result.setNScore(scores.getOrDefault("N", 0));
        result.setTScore(scores.getOrDefault("T", 0));
        result.setFScore(scores.getOrDefault("F", 0));
        result.setJScore(scores.getOrDefault("J", 0));
        result.setPScore(scores.getOrDefault("P", 0));
        result.setCreateTime(DateUtils.getNowDate());

        // 获取人格类型描述
        MbtiPersonalityType personalityDesc = personalityTypeMapper.selectMbtiPersonalityTypeByTypeCode(personalityType);
        if (personalityDesc != null)
        {
            result.setResultDescription(personalityDesc.getDescription());
        }

        resultMapper.insertMbtiResult(result);
        return result;
    }

    /**
     * 计算各维度得分
     */
    private Map<String, Integer> calculateDimensionScores(List<MbtiAnswer> answers)
    {
        Map<String, Integer> scores = new HashMap<>();
        scores.put("E", 0);
        scores.put("I", 0);
        scores.put("S", 0);
        scores.put("N", 0);
        scores.put("T", 0);
        scores.put("F", 0);
        scores.put("J", 0);
        scores.put("P", 0);

        for (MbtiAnswer answer : answers)
        {
            MbtiOption option = optionMapper.selectMbtiOptionByOptionId(answer.getOptionId());
            if (option != null && StringUtils.isNotEmpty(option.getTendency()))
            {
                String tendency = option.getTendency();
                scores.put(tendency, scores.get(tendency) + option.getScore());
            }
        }

        return scores;
    }

    /**
     * 确定人格类型
     */
    private String determinePersonalityType(Map<String, Integer> scores)
    {
        StringBuilder type = new StringBuilder();
        
        // E vs I
        type.append(scores.get("E") >= scores.get("I") ? "E" : "I");
        
        // S vs N
        type.append(scores.get("S") >= scores.get("N") ? "S" : "N");
        
        // T vs F
        type.append(scores.get("T") >= scores.get("F") ? "T" : "F");
        
        // J vs P
        type.append(scores.get("J") >= scores.get("P") ? "J" : "P");
        
        return type.toString();
    }

    /**
     * 获取测试结果
     */
    @Override
    public Map<String, Object> getTestResult(Long recordId)
    {
        MbtiResult result = resultMapper.selectResultByRecordId(recordId);
        if (result == null)
        {
            throw new ServiceException("测试结果不存在");
        }

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("personalityType", result.getPersonalityType());

        // 创建分数Map
        Map<String, Integer> scores = new HashMap<>();
        scores.put("E", result.getEScore());
        scores.put("I", result.getIScore());
        scores.put("S", result.getSScore());
        scores.put("N", result.getNScore());
        scores.put("T", result.getTScore());
        scores.put("F", result.getFScore());
        scores.put("J", result.getJScore());
        scores.put("P", result.getPScore());
        resultMap.put("scores", scores);

        // 获取详细描述
        MbtiPersonalityType personalityType = personalityTypeMapper.selectMbtiPersonalityTypeByTypeCode(result.getPersonalityType());
        if (personalityType != null)
        {
            resultMap.put("typeName", personalityType.getTypeName());
            resultMap.put("typeNickname", personalityType.getTypeNickname());
            resultMap.put("description", personalityType.getDescription());
            resultMap.put("strengths", personalityType.getStrengths());
            resultMap.put("weaknesses", personalityType.getWeaknesses());
            resultMap.put("careerSuggestions", personalityType.getCareerSuggestions());
            resultMap.put("relationshipTips", personalityType.getRelationshipTips());
            resultMap.put("famousPeople", personalityType.getFamousPeople());
            resultMap.put("percentage", personalityType.getPercentage());
        }

        return resultMap;
    }

    /**
     * 根据人格类型获取详细描述
     */
    @Override
    public MbtiPersonalityType getPersonalityTypeDescription(String personalityType)
    {
        return personalityTypeMapper.selectMbtiPersonalityTypeByTypeCode(personalityType);
    }

    /**
     * 获取用户的测试历史
     */
    @Override
    public List<Map<String, Object>> getUserTestHistory(Long userId)
    {
        List<MbtiTestRecord> records = testRecordMapper.selectTestRecordsByUserId(userId);
        List<Map<String, Object>> result = new ArrayList<>();

        for (MbtiTestRecord record : records)
        {
            Map<String, Object> recordMap = new HashMap<>();
            recordMap.put("recordId", record.getRecordId());
            recordMap.put("testTypeId", record.getTestTypeId());
            recordMap.put("startTime", record.getStartTime());
            recordMap.put("endTime", record.getEndTime());
            recordMap.put("duration", record.getDuration());
            recordMap.put("status", record.getStatus());

            // 获取测试类型信息
            MbtiTestType testType = testTypeMapper.selectMbtiTestTypeByTestTypeId(record.getTestTypeId());
            if (testType != null)
            {
                recordMap.put("testTypeName", testType.getTypeName());
            }

            // 获取测试结果
            if ("1".equals(record.getStatus()))
            {
                MbtiResult testResult = resultMapper.selectResultByRecordId(record.getRecordId());
                if (testResult != null)
                {
                    recordMap.put("personalityType", testResult.getPersonalityType());
                }
            }

            result.add(recordMap);
        }

        return result;
    }

    /**
     * 获取测试进度
     */
    @Override
    public Map<String, Object> getTestProgress(Long recordId)
    {
        MbtiTestRecord record = testRecordMapper.selectMbtiTestRecordByRecordId(recordId);
        if (record == null)
        {
            throw new ServiceException("测试记录不存在");
        }

        MbtiTestType testType = testTypeMapper.selectMbtiTestTypeByTestTypeId(record.getTestTypeId());
        List<MbtiAnswer> answers = answerMapper.selectAnswersByRecordId(recordId);

        Map<String, Object> progress = new HashMap<>();
        progress.put("totalQuestions", testType.getQuestionCount());
        progress.put("answeredQuestions", answers.size());
        progress.put("progress", (double) answers.size() / testType.getQuestionCount() * 100);
        progress.put("status", record.getStatus());
        progress.put("startTime", record.getStartTime());

        return progress;
    }

    /**
     * 放弃测试
     */
    @Override
    @Transactional
    public boolean abandonTest(Long recordId)
    {
        MbtiTestRecord record = testRecordMapper.selectMbtiTestRecordByRecordId(recordId);
        if (record == null || !"0".equals(record.getStatus()))
        {
            return false;
        }

        record.setStatus("2"); // 已放弃
        record.setEndTime(DateUtils.getNowDate());
        return testRecordMapper.updateMbtiTestRecord(record) > 0;
    }

    /**
     * 验证测试记录是否有效
     */
    @Override
    public boolean validateTestRecord(Long recordId)
    {
        MbtiTestRecord record = testRecordMapper.selectMbtiTestRecordByRecordId(recordId);
        return record != null && "0".equals(record.getStatus());
    }

    /**
     * 获取MBTI统计数据
     */
    @Override
    public Map<String, Object> getMbtiStatistics()
    {
        // 这里可以实现统计逻辑，比如各人格类型的分布等
        Map<String, Object> statistics = new HashMap<>();
        // TODO: 实现统计逻辑
        return statistics;
    }

    /**
     * 重新计算测试结果
     *
     * @param recordId 测试记录ID
     * @return 测试结果
     */
    @Override
    @Transactional
    public MbtiResult calculateTestResult(Long recordId)
    {
        // 验证测试记录
        MbtiTestRecord record = testRecordMapper.selectMbtiTestRecordByRecordId(recordId);
        if (record == null)
        {
            throw new ServiceException("测试记录不存在");
        }

        // 获取所有答案
        List<MbtiAnswer> answers = answerMapper.selectAnswersByRecordId(recordId);
        if (answers.isEmpty())
        {
            throw new ServiceException("未找到答题记录，无法计算结果");
        }

        // 计算各维度得分
        Map<String, Integer> scores = calculateDimensionScores(answers);

        // 确定人格类型
        String personalityType = determinePersonalityType(scores);

        // 创建或更新测试结果
        MbtiResult existingResult = resultMapper.selectResultByRecordId(recordId);

        MbtiResult result = new MbtiResult();
        result.setRecordId(recordId);
        result.setPersonalityType(personalityType);
        result.setEScore(scores.getOrDefault("E", 0));
        result.setIScore(scores.getOrDefault("I", 0));
        result.setSScore(scores.getOrDefault("S", 0));
        result.setNScore(scores.getOrDefault("N", 0));
        result.setTScore(scores.getOrDefault("T", 0));
        result.setFScore(scores.getOrDefault("F", 0));
        result.setJScore(scores.getOrDefault("J", 0));
        result.setPScore(scores.getOrDefault("P", 0));

        // 获取人格类型描述
        MbtiPersonalityType personalityDesc = personalityTypeMapper.selectMbtiPersonalityTypeByTypeCode(personalityType);
        if (personalityDesc != null)
        {
            result.setResultDescription(personalityDesc.getDescription());
        }

        if (existingResult != null)
        {
            // 更新现有结果
            result.setResultId(existingResult.getResultId());
            result.setCreateTime(existingResult.getCreateTime());
            result.setUpdateTime(DateUtils.getNowDate());
            resultMapper.updateMbtiResult(result);
        }
        else
        {
            // 插入新结果
            result.setCreateTime(DateUtils.getNowDate());
            resultMapper.insertMbtiResult(result);
        }

        return result;
    }
}
